// "This sample program is provided AS IS and may be used, executed, copied and modified without royalty payment by customer (a) for its own
// instruction and study, (b) in order to develop applications designed to run with an IBM WebSphere product, either for customer's own internal use
// or for redistribution by customer, as part of such an application, in customer's own products. "
//
// (C) COPYRIGHT International Business Machines Corp., 2005,2006
// All Rights Reserved * Licensed Materials - Property of IBM

package com;

import java.util.concurrent.Executor;

import com.ibm.websphere.asynchbeans.EventSource;
import com.ibm.websphere.asynchbeans.WorkManager;

/**
 * This is a wrapper for an Executor which makes sure the Runnable
 * is executed with the J2EE context of the thread invoking the execute
 * method. This context adds around 30 micro seconds to the call. For most applications
 * this shouldn't be a problem at all.
 * @author Billy Newport and Chris D Johnson
 */
public class ContextExecutor implements Executor
{
	// The WorkManager is used to get and apply the correct J2EE context.
	protected WorkManager workManager;

	// The actual executor that will run the command.
	protected Executor executor;

	/**
	 * This takes a WorkManager and any Executor; the real Executor to
	 * to execute commands on.
	 * @param workManager the WorkManager to use for establishing our J2EE context
	 * @param executor the actual Executor to run the command with.
	 */
	public ContextExecutor(WorkManager workManager, Executor executor)
	{
		super();
		this.workManager = workManager;
		this.executor = executor;
	}

	/**
	 * This creates a wrapper to the Runnable which calls the run method with
	 * the call of the execute methods J2EE context.
	 * @param command the Runnable to run on the Executor.
     * @see edu.emory.mathcs.backport.java.util.concurrent.Executor#execute(java.lang.Runnable)
     */
    public void execute(Runnable command)
    {
        // Create a snapshot of this thread's J2EE context
        // and wrap the command in a proxy.
		EventSource es = workManager.createEventSource();
		es.addListener(command);
		Runnable commandProxy = (Runnable)es.getEventTrigger(Runnable.class);

		// Pass the proxy to the real Executor. When the executor runs the Runnable
		// then our proxy is actually called, it sets up the thread and then invokes
		// the real Runnable.
		executor.execute(commandProxy);
    }
}
